import { ObjType } from '@/@type/index'
import config from '@/config'
import * as message from '@/utils/message'
import signUtil from './signUtil.js'
import * as auth from '@/utils/auth'
import * as utils from '@/utils'
import { getCurrentPage, navigateTo } from '@/utils/tools'
import dayjs from 'dayjs'
import { locSharePosterInfo, locToken } from '@/utils/locStore/data'
import awaitToken from './awaitToken'
let loadingStack: UniApp.RequestTask[] = []
type MethodType = 'GET' | 'POST'
type OptionType = UniApp.RequestOptions
const whiteList = [
  '/api/public/getToken',
  '/api/channel/baseSet',
  '/api/public/getAccount'
]
let hasGetToken = false
const needLoginErrnoCode = [
  10001,
  10005,
  10006, //未绑定手机
  60305,
  200000,
  200001,
  200002,
  10012
] // 需要特殊操作的错误码
// #ifdef H5
// 等待请求结束
function waitGetToken() {
  return new Promise((resolve) => {
    getStatus(resolve)
  })
}

function getStatus(resolve) {
  setTimeout(() => {
    if (!hasGetToken) {
      resolve()
    } else {
      getStatus(resolve)
    }
  }, 200)
}
// #endif
const axios = {
  baseOptions(params: { url?: any; data?: any }, method: MethodType = 'POST') {
    return new Promise(async (resolve, reject) => {
      const url: string = config.host + params.url
      let { data = {} } = params
      data = JSON.parse(JSON.stringify(data))
      //#ifndef H5
      if (!whiteList.includes(params.url) && !data.stopBlockApi) {
        console.log(params.url)
        await auth.watchBlockApi()
        if (!auth.getLocToken()) {
          return reject({ msg: '没有token' })
        }
      }
      //#endif
      // #ifdef H5
      if (!whiteList.includes(params.url)) {
        if (!locToken.get()) {
          if (!hasGetToken) {
            hasGetToken = true
            await auth.toGetToken()
            hasGetToken = false
          } else {
            await waitGetToken()
          }
        }
      }
      // #endif
      const hasNo = data.hasNo //报错不捕获
      const needLoading = data.needLoading || hasNo //开启loading
      data.needLoading && delete data.needLoading
      const token = auth.getLocToken() || ''
      const areaInfo = auth.getChooseAreaInfo() //已选择城市
      let uId
      let registerActivityId
      // #ifdef MP-ALIPAY
      uId = getApp().globalData.uId
      registerActivityId = getApp().globalData.registerActivityId
      // #endif
      // #ifndef MP-ALIPAY
      uId = locSharePosterInfo.get().uId
      registerActivityId = locSharePosterInfo.get().registerActivityId
      // #endif
      console.log('params', params)
      const obj = {
        account: auth.getLocAccount() || config.account || '',
        tokenId: token,
        uId: uId || '',
        registerActivityId: registerActivityId || '',
        miniAppId: auth.getMiniAppId(),
        deviceType: auth.getDeviceType(),
        cityId: areaInfo.cityId || '',
        requestTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
      }

      const password = auth.getPwd() || config.password
      let cityObj = {}

      if (!auth.getSingleModel()) {
        // 单影城，城市唯一影院唯一
        cityObj = { cityId: auth.getBaseSetCity() || areaInfo.cityId || '' }
      } else {
        // 多影城，并且当前定位城市不在接口返回的城市内，取接口返回的第一个城市
        const baseCity = auth.getBaseSetAllCity()
        if (baseCity && baseCity.indexOf(areaInfo.cityId) === -1) {
          cityObj = {
            cityId: auth.getBaseSetCity().split(',')[0] || areaInfo.cityId || ''
          }
        }
      }
      const newObj = { ...data, ...obj, ...cityObj }
      const verifyInfo = signUtil.getSign(newObj, password)

      const option: OptionType = {
        url,
        data: { ...newObj, verifyInfo },
        header: {
          withCredentials: true,
          'content-type': 'application/json;charset=UTF-8'
        },
        method: method,
        timeout: 100000,
        success: async (res) => {
          const resData = res.data as {
            status: any
            data: any
            content: string
          }
          loadingStack = loadingStack.filter((i) => i !== req)

          const status = +resData.status
          // console.log('this.first', this.first)
          // if (!this.first && url.indexOf('getCouponList') !== -1) {
          //   this.first = true
          //   status = 10001
          // }
          if (status !== 0) {
            if (hasNo) {
              reject({ myMgs: '接口报错不处理' })
            }

            if (needLoginErrnoCode.includes(status)) {
              this.clearLoading(needLoading).then(async () => {
                //特殊状态码
                if (status === 10001) {
                  await awaitToken()
                  await utils.sleep(300)
                  console.log('baseOptions params', params)
                  const rData = await axios.baseOptions(params, method)
                  console.log('baseOptions params1', rData)
                  resolve(rData)
                  console.log('baseOptions params2')
                } else if (status === 10005) {
                  if (data.mode) {
                    reject(res)
                  } else {
                    message.toast('登录已失效, 请重新登录!')
                    const { fullPath } = getCurrentPage()
                    auth.handleLogout(fullPath)
                  }
                  // auth.handleLogout(options?.sq ? fullPath : '')
                } else if (status === 10006) {
                  //未绑定手机号
                  // #ifdef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO
                  utils.debounce(navigateTo, [
                    '/pages/login/index',
                    {
                      bindMobile: 1
                    }
                  ])
                  // #endif
                  //#ifdef H5
                  uni.navigateTo({
                    url: '/subPages/bindMobile/index?bindMobile=1'
                  })
                  //#endif
                } else {
                  resData.content && message.toast(resData.content)
                }
                console.log('rejectrejectreject')
                reject(res)
              })
            } else {
              this.clearLoading(needLoading).then(() => {
                console.log(params.url)
                // #ifdef MP-TOUTIAO
                if (params.url === '/api/orderFilm/lockSeat' && status === 2) {
                } else {
                  message.toast(resData.content)
                }
                // #endif
                // #ifndef MP-TOUTIAO
                message.toast(resData.content)
                // #endif
                reject(res)
              })
            }

            // resolve(res)
          } else {
            this.clearLoading(needLoading).then(() => {
              const result = resData.data ? resData.data : resData
              resolve(result)
            })
          }
        },
        fail: (res) => {
          this.clearLoading(needLoading).then(() => {
            reject(res)
          })
        }
      }
      const req = uni.request(option)
      if (needLoading) {
        loadingStack.push(req)
        message.loading()
      }
    })
  },
  clearLoading(needLoading) {
    loadingStack = []

    return new Promise((resolve, reject) => {
      if (needLoading) {
        message.hideLoading()
        setTimeout(() => {
          resolve(true)
        }, 200)
      } else {
        resolve(true)
      }
    })
  },
  get(url: string, data?: ObjType) {
    const option = { url, data }
    return this.baseOptions(option)
  },
  post: function (url: string, data?: ObjType) {
    const params = { url, data }
    return this.baseOptions(params, 'POST')
  },
  first: false
}
export default axios

export function creatApiMap<T extends ObjType>(apiMap: T) {
  type ResultType = {
    [k in keyof T]: (data?: any) => Promise<any>
  }
  const result = {} as ResultType

  for (const key in apiMap) {
    const [url, method = 'post'] = apiMap[key].split(',')
    result[key] = (data?) => axios[method](url, data)
  }
  return result
}
